package com.design.pattern.creational.singleton;

import com.design.pattern.creational.User;
import com.design.pattern.creational.UserRelation;
import com.design.pattern.creational.singleton.eager.EnumSingleton;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.*;
import java.lang.reflect.Constructor;

/**
 * @Description Java种 存在的 4 种创建对象的实现
 * @Author houchenkai
 * @Created Date: 2021/11/3 15:34
 * @ClassName
 */
public class CreateBean {


    public static void main(String[] args) throws Exception {
        //  createdByClone();
        //  createdByReflect();
        createdBySerialization();
    }

    /**
     * 创建方式1 通过new关键字
     */
    private static void createdByNew() {
        User user = new User();
        user.setAge(1);
        user.setName("xx");
        System.out.println(user.toString());
    }

    /**
     * 创建方式2 通过实现 cloneable接口 重写Object类的clone方法    还可以通过序列化来实现clone对象
     * 存在浅克隆和深克隆
     * 浅克隆只会克隆当前类中Java类库中的类  不会克隆自建的引用类型成员变量
     * 深度克隆需要克隆类中被引用的类 也要实现 cloneable接口 在被克隆的类中调用 此类的克隆方法给手动赋值
     *
     * @throws CloneNotSupportedException
     */
    private static void createdByClone() throws CloneNotSupportedException, IOException {
        User user = new User();
        UserRelation userRelation = new UserRelation();
        userRelation.setParent("xxx");
        user.setAge(1);
        user.setName("xx");
        user.setUserRelation(userRelation);

        User clone = user.clone();
        System.out.println(clone.toString());

        // 序列化的形式进行深克隆
        ObjectMapper objectMapper = new ObjectMapper();
        User copyUser = objectMapper.readValue(objectMapper.writeValueAsString(user), User.class);


        UserRelation userRelation1 = new UserRelation();
        userRelation1.setParent("我变了");
        user.setUserRelation(userRelation1);

        System.out.println(clone.toString());
        System.out.println(copyUser.toString());


    }

    /**
     * 创建方式3 通过反射的方式创建 对象
     *  todo  私有构造方法可以防止反射破坏 单例
     * @throws Exception
     */
    private static void createdByReflect() throws Exception {
        Class<User> userClass = User.class;
        User reflectUser1 = userClass.newInstance(); //默认使用无参构造
        Constructor<User> constructor = userClass.getDeclaredConstructor();
        constructor.setAccessible(true); //暴力反射
        User reflectUser2 = constructor.newInstance();
        System.out.println(reflectUser1);
        System.out.println(reflectUser2);

    }

    /**
     * 创建方式4 通过流的序列化
     *
     * @see ObjectInputStream#checkResolve(java.lang.Object) 方法中如果是 Object 类型 则调用下面这个方法
     * @see ObjectInputStream#readOrdinaryObject(boolean) 在这个方法中会先通过反射去创建一个对象
     *       desc.hasReadResolveMethod()     如果目标类中有  readResolve 方法 则返回 readResolve方法返回的对象  可以声明此方法来 返回单例对象
     *       readResolveMethod = getInheritableMethod(cl, "readResolve", null, Object.class);
     * TODO 通过重写resolveObject方法返回单例对象 可以防止序列化破坏单例
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private static void createdBySerialization() throws IOException, ClassNotFoundException {
        User user = new User();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.obj"));
        objectOutputStream.writeObject(user);

        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("user.obj"));
        User serializationUser = (User) objectInputStream.readObject();
        System.out.println(serializationUser);

    }
}
